<?php

namespace Pinenut\Model2\Embedded;

use Pinenut\Model2\Embedded;

/**
 * Ассоциативный массив встроенных объектов
 *
 * @author kosh
 *        
 */
class Assoc extends Embedded implements \ArrayAccess, \Iterator, \Countable {

	protected $_container = [ ];
	
	protected $_embedded;
	
	/**
	 * Установка параметров для объекта коллекции при определении структуры модели
	 *
	 * @param \Pinenut\Model2\Embedded $reference
	 * @param string $className
	 * @param string $fieldName
	 */
	function __construct($field, array $params = array()) { //Embedded $parent, 
		parent::__construct ( $field ); //$parent, 
		
		$embeddedClass = array_shift ( $params );
			
		$this->_embedded = new $embeddedClass ( $this, $field );

	}
	
	
	/**
	 */
	public function offsetSet($offset, $value) {
		if (!($value instanceof Embedded)) {
			// готовим объект
			$object = clone $this->_embedded;
			$object->populate($value, false);
			$this->_container[$offset] = $object;
		} else {
			$this->_container[$offset] = $value;
		}
	}
	
	/**
	 * Проверяем существование связи
	 * В простом случае - только у нас, а для связей хранящихся не у нас,
	 * но на нас - должны проверить обратную ссылку
	 */
	public function offsetExists($offset) {
		return isset ( $this->_container [( string ) $offset] );
	}
	
	/**
	 * Удаляем связь
	 * TODO: сгенерить апдейт на удаление связи
	 */
	public function offsetUnset($offset) {
		// запускаем процедуру удаления связи
		unset ( $this->_container [( string ) $offset] );
	}
	
	/**
	 * Возвращаем связь, если не существует - создаём
	 */
	public function offsetGet($offset) {
		$id = ( string ) $offset;
		// ищем связь в контейнере,
		if (! isset ( $this [$id] )) {
			// создаём и возвращаем пустышку
			$this[$id] = [];
//			echo "<pre>";print_r($this->_container); exit;
		}
		// возвращаем её
		return $this->_container [$id];
	}
	
	// Iterator
	function rewind() {
		return reset ( $this->_container );
	}
	function current() {
		return current ( $this->_container );
	}
	function key() {
		return key ( $this->_container );
	}
	function next() {
		return next ( $this->_container );
	}
	function valid() {
		return key ( $this->_container ) !== null;
	}
	function isEmpty() {
		return empty ( $this->_container );
	}
	function count() {
		return count ( $this->_container );
	}
	public function toArray() {
		$data = [ ];
		foreach ( $this->_container as $key => $embedded) {
			if (method_exists ( $embedded, 'toArray' )) {
				$data [$key] = $embedded->toArray ();
			}
		}
	}
	
	public function populate($data = array(), $fromDatabase = true) {
		// населяем контейнер массивом связей
		$this->_container = [];
		
		if (!empty($data)) foreach ($data as $key=>$value) {
			$this[$key] = $value;
		}
	}
	
	protected function updaters() {
		$isNew = $this->isNew();
		foreach ($this->_container as $key=>$embedded) {
			/* @var $embedded \Pinenut\Model2\Embedded */
				
			$updaters = $embedded->updaters();

				
			foreach ($updaters as $updater) {
				$updater->prependFieldNames($key);
				$this->addUpdater($updater);
			}
		}
	
		// грохаем модификаторы
		// TODO: вынести в afterSave
		$updaters = $this->getUpdaters(true);
		// 		echo "many updaters:";
		// 		print_r($updaters);
		return $updaters;
	}
}